package com.sh.service.impl;

import com.sh.common.enums.OssTypeEnum;
import com.sh.common.pojo.bo.PutObjectRes;
import com.sh.config.OssClientConfig;
import com.sh.service.IOSSService;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

@Slf4j
public class MinioService implements IOSSService {

    private MinioClient minioClient;

    private OssClientConfig ossClientConfig;

    public MinioService(OssClientConfig ossClientConfig) {
        this.ossClientConfig = ossClientConfig;
        if (OssTypeEnum.MINIO.getCode().equals(ossClientConfig.getResourceType())) {
            minioClient = MinioClient.builder()
                    .endpoint(ossClientConfig.getEndpoint())
                    .credentials(ossClientConfig.getAccessKey(), ossClientConfig.getSecretKey())
                    .build();
        }
    }

    @Override
    public InputStream getObject(String bucketName, String prefix) {
        try {
            return minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(prefix)
                    .build());
        } catch (Exception e) {
            log.error("get object error", e);
        }
        return null;
    }

    @Override
    public String signUrl(String bucketName, String objectName, Integer expires) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .method(Method.GET)
                    .expiry(expires, TimeUnit.DAYS)
                    .build());
        } catch (Exception e) {
            log.error("url signed error", e);
        }
        return null;
    }

    @Override
    public PutObjectRes putObject(String bucketName, String objectName, String content) {
        try {
            byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .stream(inputStream, bytes.length, -1)
                    .build());
            return PutObjectRes.builder()
                    .success(true)
                    .etag(objectWriteResponse.etag())
                    .versionId(objectWriteResponse.versionId())
                    .build();
        } catch (Exception e) {
            log.error("put object error", e);
            return PutObjectRes.builder().success(false).build();
        }
    }

    @Override
    public PutObjectRes putObject(String objectName, MultipartFile file) {
        try {
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder()
                    .bucket(ossClientConfig.getBucket())
                    .object(objectName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
            return PutObjectRes.builder()
                    .success(true)
                    .etag(objectWriteResponse.etag())
                    .versionId(objectWriteResponse.versionId())
                    .build();
        } catch (Exception e) {
            log.error("put object error", e);
            return PutObjectRes.builder().success(false).build();
        }
    }

    @Override
    public String signUrl(String objectName) {
        return signUrl(ossClientConfig.getBucket(), objectName, ossClientConfig.getSignExpires());
    }

    @Override
    public String signUrl(String objectName, Integer expires) {
        if (expires == null || expires < 1 || expires > 7) {
            expires = ossClientConfig.getSignExpires();
        }
        return signUrl(ossClientConfig.getBucket(), objectName, expires);
    }

    @Override
    public PutObjectRes putObject(String objectName, String content) {
        return putObject(ossClientConfig.getBucket(), objectName, content);
    }

    @Override
    public Boolean copyObject(String srcObject, String destObject) {
        try {
            minioClient.copyObject(CopyObjectArgs.builder()
                    .bucket(ossClientConfig.getBucket())
                    .object(destObject)
                    .source(CopySource.builder()
                            .bucket(ossClientConfig.getBucket())
                            .object(srcObject)
                            .build())
                    .build());
            return true;
        } catch (Exception e) {
            log.error("文件复制失败", e);
            return false;
        }
    }
}
